package com.tbit.uqbike.webmanager.util.csv.util;


import cn.hutool.core.date.DateUtil;
import com.tbit.uqbike.webmanager.util.csv.annotations.Csv;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Slf4j
public class CSVUtils {


    public static void writeHead(Class c, File file) {
        write(null, c, file, true);
    }

    public static void writeList(List dataList, Class c, File file) {
        write(dataList, c, file, false);
    }


    public static void write(List dataList, Class c, File file, boolean isHead) {
        BufferedWriter buffWriter = null;
        try {
            File parent = file.getParentFile();
            if (parent != null && !parent.exists()) {
                parent.mkdirs();
            }
            file.createNewFile();
            FileWriter writer = new FileWriter(file, true);
            buffWriter = new BufferedWriter(writer, 1024);

            List<FieldInfo> fieldInfos = getFieldInfos(c);

            if (isHead) {
                StringBuffer buf = new StringBuffer();
                fieldInfos.forEach(v -> {
                    String name = v.getExcel().name();
                    buf.append("\"").append(name).append("\",").toString();
                });

                buffWriter.write(buf.toString());
                buffWriter.newLine();
            } else {
                if (!dataList.isEmpty()) {
                    for (Object row : dataList) {
                        StringBuffer buf = new StringBuffer();

                        fieldInfos.forEach(v -> {

                            try {
                                Object o = v.getMethod.invoke(row);
                                if (o == null) {
                                    o = "";
                                }
                                if (o instanceof Date) {
                                    o = DateUtil.format((Date) o, "yyyy-MM-dd HH:mm:ss");
                                }
                                String[] keys = v.getExcel().keys();
                                String[] values = v.getExcel().values();
                                for (int i = 0; i < keys.length; i++) {
                                    if (keys[i].equals(o.toString())) {
                                        o = values[i];
                                    }
                                }
                                buf.append("\"").append(o).append("\",").toString();
                            } catch (Exception e) {
                                log.error(e.getMessage(), e);
                            }

                        });
                        buffWriter.write(buf.toString());
                        buffWriter.newLine();
                    }
                }
            }
            buffWriter.flush();
        } catch (Exception e) {
            throw new RuntimeException("csv写入错误", e);
        } finally {
            try {
                if (buffWriter != null) {
                    buffWriter.close();
                }
            } catch (IOException e) {
                log.error(e.getMessage(), e);
            }
        }

    }

    private static List<FieldInfo> getFieldInfos(Class c) throws NoSuchMethodException {
        List<FieldInfo> iInfos = new ArrayList<>();
        Field[] fields = c.getDeclaredFields();
        for (Field field : fields) {
            Csv csv = field.getDeclaredAnnotation(Csv.class);
            if (csv != null) {
                String field_name = field.getName();
                Method method = c.getDeclaredMethod("get" + Character.toUpperCase(field_name.charAt(0)) + field_name.substring(1));
                FieldInfo fieldInfo = new FieldInfo();
                fieldInfo.setExcel(csv);
                fieldInfo.setField(field);
                fieldInfo.setGetMethod(method);
                iInfos.add(fieldInfo);
            }
        }
        return iInfos;
    }

    @Data
    public static class FieldInfo {
        public Field field;
        public Method getMethod;
        public Csv excel;
    }


}
